#include <iostream>
#include <unistd.h>
#include <cstring> //C++版本的string.h
#include <cerrno>  //C++版本的errno.h
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <fcntl.h>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>

void sigcb(int sig)
{
    std::cout << " get a sig: " << sig << std::endl;
}

int main()
{
    int i = 5;
    int j = 5;
    std::cout << getpid() << std::endl;

    sigset_t lnew, lold, lwait;   //三个信号集
    struct sigaction act;
    act.sa_handler = sigcb;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(2, &act, 0);    //可以捕捉以下三个信号：SIGINT/SIGQUIT/SIGUSR1
    sigaction(SIGQUIT, &act, 0);
    sigaction(40, &act, 0);
   
    sigemptyset(&lnew);
    sigaddset(&lnew, SIGINT);  //SIGINT信号加入到new信号集中
    sigemptyset(&lwait);
    sigaddset(&lwait, 40);  //SIGUSR1信号加入wait
    sigprocmask(SIG_BLOCK, &lnew, &lold);       //将SIGINT阻塞，保存当前信号集到old中
   
    //临界区代码执行    


    if(sigsuspend(&lwait) == -1)  //程序在此处挂起；用wait信号集替换new信号集。即：过来SIGUSR1信  号，阻塞掉，程序继续挂起；过来其他信号，例如SIGINT，则会唤醒程序。执行sigsuspend的原子操作。注意：如果“sigaddset(&wait, SIGUSR1);”这句没有，则此处不会阻塞任何信号，即过来任何信号均会唤醒程序。
        pause();
    printf("After sigsuspend");
    sigprocmask(SIG_SETMASK, &lold, NULL);



    // sigset_t lnew,lold;
    // struct sigaction act;
    // act.sa_handler = sigcb;  //信号处理函数handler
    // sigemptyset(&act.sa_mask);
    // act.sa_flags = 0;
    // sigaction(2, &act, 0);  //准备捕捉SIGINT信号
    // sigemptyset(&lnew);
    // sigaddset(&lnew, 2);
    // sigprocmask(SIG_BLOCK, &lnew, &lold);  //将SIGINT信号阻塞，同时保存当前信号集
    // std::cout << "Blocked because of 2" << std::endl;
    // sigprocmask(SIG_SETMASK, &lold, NULL);  //取消阻塞
    // pause();

    // sigaction(40, &act, 0);  //准备捕捉40号信号
    // sigemptyset(&lnew);
    // sigaddset(&lnew, 40);
    // sigprocmask(SIG_BLOCK, &lnew, &lold);  //将40号信号阻塞，同时保存当前信号集
    // std::cout << "Blocked because of 40" << std::endl;
    // sigprocmask(SIG_SETMASK, &lold, NULL);  //取消阻塞
    // pause();
    while (i--)
    {
        kill(getpid(), 40);
        kill(getpid(), 2);

        // sleep(1);
    }

    // while (j--)
    // {
    //     kill(getpid(), 40);
    //     // sleep(1);
    // }

}

// int main()
// {
//     struct sigaction act, oact;
//     act.sa_handler = sigcb;
//     sigemptyset(&act.sa_mask);
//     act.sa_flags = 0;
//     sigaction(SIGFPE, &act, &oact);
//     int a = 10;
//     a /= 0;
//     return 0;
// }

// int main()
// {
//     signal(SIGFPE, sigcb);
//     int a = 10;
//     a /= 0;
//     return 0;
// }

// void handler(int sig)
// {
//     std::cout << " get a sig: " << sig << std::endl;
// }

// int main()
// {
//     signal(SIGSEGV, handler);
//     signal(SIGFPE, handler);
//     //  崩溃了为什么会退出？  默认是终止进程
//     //  可以不退出吗？可以，直接使用signal 函数重写默认动作，捕捉异常，但是不建议这样做

//     // int a = 10;
//     // a /= 0;        // 触发8号错误    (8) SIGFPE
//     int *p = nullptr;
//     *p = 100;         // 触发11号错误   (11) SIGSEGV
//     while (true)
//     {
//         std::cout << "hello bit, pid: " << getpid() << std::endl;
//     }
// }

// int cnt = 0;

// void handler(int signal)
// {
//     std::cout << "cnt " << cnt << " get a sig: " << signal << std::endl;
//     exit(1);
// }

// int main()
// {
//     signal(SIGALRM, handler);
//     alarm(5);   //设定一秒后的闹钟
//     sleep(2);
//     int n = alarm(0);
//     std::cout << "n: " << n << std::endl;
//     sleep(10);
//     while (true)
//     {
//         // std::cout << "cnt: " << cnt << std::endl;
//         cnt++;
//     }
// }

// void handler(int signal)
// {
//     std::cout << "get a sig: " << signal << std::endl;
// }

// int main()
// {
//     int cnt = 0;
//     signal(SIGABRT, handler);
//     while (true)
//     {
//         sleep(2);
//         abort();
//     }

// }

// int main(int argc, char *argv[])
// {
//     if (argc != 3)
//     {
//         std::cerr << "Usage: " << argv[0] << "signum pid" << std::endl;
//         return 1;
//     }
//     pid_t pid = std::stoi(argv[2]);
//     int signum = std::stoi(argv[1]);
//     kill(pid, signum);

//     return 0;
// }

// void handler(int signal)
// {
//     std::cout << "get a sig: " << signal << std::endl;
// }

// int main()
// {
//     //对信号的自定义捕捉，我们只要捕捉一次，后续就会有效
//     signal(2, handler);
//     signal(3, handler);
//     signal(4, handler);
//     signal(5, handler);
//     while (true)
//     {
//         std::cout << "hello bit, pid: " << getpid() << std::endl;
//         sleep(1);
//     }
//     return 0;
// }
